<?php

//constants
define('AUTH_EXACT', 			1); //you need to be exact that auth level
define('AUTH_GREATER',	 	2); //you need to be that exact level or greater
define('AUTH_JUST_TEST', 	3); //just test if you are exact that level, dont redirect to login

/**
 * User management plugin
 *
 * @version $Id$
 * @copyright 2010
 */
class User extends Plugin
{
	public $plugin_name = "User"; //name of plugin
	public $plugin_short_desc = "User management"; //short description of plugin
	public $plugin_long_desc = "User managemend, login, register, profile"; //longer description - what does plugin do
	public $version = "1.0"; //version of plugin
	public $has_sidebar = true; //does this plugin have sidebar -> function generate_sidebar()
	public $has_footer = false; //does this plugin have footer -> function generate_footer()
	public $needs_install = true;

	private $user;

	/**
	 * Constructor
	 */
	function __construct()
	{
		global $theme,$db;
		$theme->set_title('User'); //set page <title>
		$this->db = $db;

		$query = $this->db->query("SELECT * FROM ".DB_PREFIX."yaps_user_authlevels");
		while($row = $this->db->get_row($query))
		{
			$name = strtoupper('ACL_'.$row['desc']);
			define($name,$row['auth_level']);
		}
	}

	/**
	 * User::logged_in()
	 * Is user logged in?
	 * @return
	 */
	public function logged_in()
	{
		 return $_SESSION['logged_in'];
	}

	/**
	 * User::get_logged_user()
	 * Return logged user object
	 * @return
	 */
	public function get_logged_user()
	{
		if($this->user) return $this->user; //load it

		if($_SESSION['user']->id > 0)
		{
			$user = $this->get_user($_SESSION['user']->id);
			$user = $this->load_profile_fields($user);
			$this->user = $user; //save it
			return $user;
		}
		return false;
	}

	/**
	 * User::get_user()
	 * Return user object with given $id
	 * @param mixed $id
	 * @return
	 */
	public function get_user($id)
	{
		$user = $this->db->get_object("SELECT U.id, U.login, U.email, U.password, U.auth_level, UA.desc AS auth_level_desc FROM ".DB_PREFIX."yaps_user U JOIN ".DB_PREFIX."yaps_user_authlevels UA ON U.auth_level = UA.auth_level WHERE U.id = ;",$id);
		$user = $this->load_profile_fields($user);
		return $user;
	}

	/**
	 * User::load_profile_fields()
	 * Load custom profile fields to user object
	 * @param mixed $user
	 * @return
	 */
	public function load_profile_fields($user)
	{
		$res = $this->db->query("SELECT PF.*, UF.value FROM ".DB_PREFIX."yaps_user_profilefields PF
														 JOIN ".DB_PREFIX."yaps_user_userfields UF ON PF.id = UF.id_field
														 WHERE UF.id_user = ;
														 ORDER BY PF.name", $user->id);

		if($this->db->num_rows($res) > 0)
		{
			$rows = $this->db->get_rows($res);
			for($i = 0; $i < sizeof($rows); $i++)
			{
				$user->$rows[$i]['name'] = $rows[$i]['value'];
			}
		}

		return $user;
	}

	/**
	 * User::login_user()
	 * Log user with selected id
	 * @param mixed $id
	 * @param bool $referer_refresh if true it will redirect to http referer, else to user-profile
	 * @return
	 */
	private function login_user($id,$referer_refresh = true)
	{
		global $core,$theme;

		$user = $this->get_user($id);

		if($user->auth_level < 1) //if user have lower than user auth level, grant him user auth level
		{
			$user->auth_level = 1;
			$this->db->query("UPDATE ".DB_PREFIX."yaps_user SET auth_level = ; WHERE id = ;",$user->auth_level,$user->id);
		}

		$_SESSION['logged_in'] = true;
		$_SESSION['user'] = $user;

		if($referer_refresh) $core->refresh_header($core->load_last_page());
		else $core->refresh_header('user-profile');
	}

	/**
	 * User::logout()
	 * Log user out, destroy sessions and refresh page
	 * @return
	 */
	public function logout()
	{
		global $core;

		unset($_SESSION['user']);
		$_SESSION['logged_in'] = 0;
		$core->refresh_header("");
	}

	/**
	 * User::login()
	 * Login form + link for registration and forgotten password
	 * @return
	 */
	public function login()
	{
		global $theme;

		$theme->include_validation();

		$form = new Form('login');
		$form->register_handler('user','handler_login');
		$form->jquery_validation();
		$form->addText('login','Login')->mandatory();
		$form->addPassword('password','Password')->mandatory()->hash_this();
		$form->render();

		echo $theme->link('Register','user','register');
	}

	/**
	 * User::handler_login()
	 * Form handler for login
	 * @param mixed $name
	 * @return
	 */
	public function handler_login($name)
	{
		global $core,$theme;

		$theme->render = false;
		$form = Form::load($name);
		$form->update();
		if(!$form->error)
		{
			$res = $this->db->query("SELECT id FROM ".DB_PREFIX."yaps_user WHERE login = ; AND password = ;",$form->field('login'),$core->md5($form->field('password')));

			if($this->db->num_rows($res) > 0) //successful login
			{
				$user = $this->db->get_row($res);
				$form->remove();
				$this->login_user($user['id'],false);
			}
			else
			{
				$core->err("Bad login or password!");
				$form->return_back();
			}
		}
		else
		{
			$form->return_back();
		}
	}

	/**
	 * User::generate_sidebar()
	 * Generate simple sidebar
	 * @return
	 */
	public function generate_sidebar()
	{
		global $core,$theme;

		$user = $this->get_logged_user();
		if(!$user)
		{
			$auth_level = 0;
			$auth_level_desc = 'Anonymous';
		}
		else
		{
			$auth_level = $user->auth_level;
			$auth_level_desc = $user->auth_level_desc;
		}

		$out = '<ul>';
		$res = $this->db->get_objects("SELECT * FROM ".DB_PREFIX."yaps_user_menu WHERE auth_level = ; ORDER BY text ASC",$auth_level);
		for($i = 0; $i < sizeof($res); $i++)
		{
			$out .= '<li><a href="'.((strlen($resp[$i]->url) > 0) ? $res[$i]->url : $res[$i]->plugin.'-'.$res[$i]->action).'">'.$res[$i]->text.'</a></li>';
		}
		$out .= '<li>ACL level: <b>'.$auth_level_desc.'</b></ul>';
		$out .= '</ul>';

		$theme->assign('sidebar',$out);
	}

	/**
	 * User::register()
	 * User registration
	 * @return
	 */
	public function register()
	{
		global $theme;

		$theme->include_validation();

		$form = new Form('registrace');
		$form->register_handler('user','handler_register');
		$form->jquery_validation();
		$form->db_table(DB_PREFIX.'yaps_user');
		$form->addText('login','Login')->mandatory()->dbcol('login');
		$form->addText('email','E-mail')->mandatory()->dbcol('email');
		$form->addPassword('password','Password')->mandatory()->dbcol('password')->hash_this();
		$form->addPassword('password2','Password again')->mandatory()->sameas('password');
		$form->render();
	}

	/**
	 * User::handler_register()
	 * Form handler for registration
	 * @param mixed $name
	 * @return
	 */
	public function handler_register($name)
	{
		global $core,$theme;

		$theme->render = false;
		$form = Form::load($name);
		$form->update();
		if(!$form->error)
		{
			if($this->db->num_rows("SELECT id FROM ".DB_PREFIX."yaps_user WHERE login = ;",$form->field('login')))
			{
				$core->err("This login is taken, please choose another one");
				$form->return_back();
			}
			elseif($form->db_insert == true) //we will insert data from form to db
			{
				$form->insert_to_db();
				if($form->error) $form->return_back();

				$form->remove();
				$this->login_user($this->db->get_last_id(),false);
			}
		}
		else
		{
			$form->return_back();
		}
	}

	public function profile()
	{
		global $core,$theme;

		if($this->logged_in())
		{
			$user = $this->get_logged_user();

			echo '<h2>Login</h2>';

			$form1 = new Form('login_update');
			$form1->use_default_handler('user-profile');
			$form1->db_update(DB_PREFIX.'yaps_user');
			$form1->addText('email','E-mail',$user->email)->dbcol('email')->minlen(3); //->regexp(REGEXP_EMAIL);
			$form1->addPassword('password','Password')->dbcol('password')->hash_this();
			$form1->addPassword('password2','Password again')->sameas('password');
			$form1->addHidden('user_id',$user->id)->dbid('id');
			$form1->render();

			$res = $this->db->query("SELECT id,name,type+0 AS type,label FROM ".DB_PREFIX."yaps_user_profilefields ORDER BY label");
			if($this->db->num_rows($res) > 0)
			{
				echo '<br /><h2>Custom profile fields</h2>';

				$form2 = new Form('custom_profile');
				$form2->register_handler('user','handler_update_profile');

				$rows = $this->db->get_rows($res);
				for($i = 0; $i < sizeof($rows); $i++)
				{
					$form2->add($rows[$i]['name'],$rows[$i]['type'],$rows[$i]['label'],$user->$rows[$i]['name']);
				}

				$form2->addHidden('user_id',$user->id);
				$form2->render();

				/*print_r($user);
				echo '<br />-----------------------------<br />';
				print_r($form2);*/
			}
		}
		else
		{
			$core->err("Please log in");
			$core->refresh_header('user-login');
		}
	}

	public function handler_update_profile($name)
	{
		global $core, $theme;

		$theme->render = false;
		$form = Form::load($name);
		$form->update();
		if(!$form->error)
		{
			$res = $this->db->query("SELECT * FROM ".DB_PREFIX."yaps_user_profilefields ORDER BY name");
			$user = $this->get_logged_user();

			$rows = $this->db->get_rows($res);
			for($i = 0; $i < sizeof($rows); $i++)
			{
				//is there any field?
				if($this->db->num_rows("SELECT id FROM ".DB_PREFIX."yaps_user_userfields WHERE id_user = ; AND id_field = ;",$user->id,$rows[$i]['id']) > 0)
				{
					//lets update it
					$this->db->query("UPDATE ".DB_PREFIX."yaps_user_userfields SET value = ; WHERE id_user = ; AND id_field = ;",$form->field($rows[$i]['name']),$user->id,$rows[$i]['id']);
				}
				else
				{
					//we must insert new row
					$this->db->query("INSERT INTO ".DB_PREFIX."yaps_user_userfields SET value = ;, id_user = ;, id_field = ;",$form->field($rows[$i]['name']),$user->id,$rows[$i]['id']);
				}
			}

			$core->msg("Profile fields have been updated!");

			$form->remove();
			$core->refresh_header('user-profile');
		}
		else
		{
			$form->return_back();
		}
	}

	/**
	 * User::is_auth()
	 * Auth function, uses user auth level
	 * @param mixed $level
	 * @param mixed $rule AUTH_EXACT or AUTH_GREATER
	 * @param string $redirect WEB_URL will be included
	 * @return
	 */
	public function is_auth($level,$rule = AUTH_EXACT,$redirect = 'user-login')
	{
		global $core;

		//if we are logged as sysadmin then dont check :)
		if($_SESSION['yaps_auth'] == true) return true;

		if(!$this->user) $this->get_logged_user();

		if($rule == AUTH_EXACT)
		{
			if($this->user->auth_level == $level) return true;
			else
			{
				$core->err('You dont have permission for that!');
				$core->refresh_header($redirect);
			}
		}
		elseif($rule == AUTH_GREATER)
		{
			if($this->user->auth_level >= $level) return true;
			else
			{
				$core->err('You dont have permission for that!');
				$core->refresh_header($redirect);
			}
		}
		elseif($rule == AUTH_JUST_TEST)
		{
			if($this->user->auth_level == $level) return true;
		}

		return false;
	}

	/**
	 * User::start()
	 * Shows login page or profile page
	 * @return
	 */
	public function start()
	{
		global $theme;

		if($this->logged_in()) $this->profile();
		else $this->login();
	}

	/**
	 * User::edit_user()
	 * Edit user
	 * @param mixed $id
	 * @return
	 */
	private function edit_user($id)
	{
		global $theme;

		$user = $this->db->get_object('SELECT * FROM '.DB_PREFIX.'yaps_user WHERE id = ;',$id);
		if($user)
		{
			echo '<br /><h2>Edit user - '.$user->login.'</h2><p>If you want to edit users profile, then use "Log as" icon in administration.</p>';
			$form1 = new Form('login_update');
			$form1->use_default_handler('admin-pluginsettings?plugin=user');
			$form1->jquery_validation();
			$form1->db_update(DB_PREFIX.'yaps_user');
			$form1->addText('login','Login',$user->login)->mandatory()->dbcol('login');
			$form1->addText('email','E-mail',$user->email)->dbcol('email')->minlen(3); //->regexp(REGEXP_EMAIL);
			$form1->addPassword('password','Password')->dbcol('password')->hash_this();
			$form1->addPassword('password2','Password again')->sameas('password');
			$form1->addSelect('auth_level','Auth level',$user->auth_level)->mandatory()->dbcol('auth_level')->add_options_from_db("SELECT `desc` AS text, auth_level AS value FROM ".DB_PREFIX."yaps_user_authlevels");
			$form1->addHidden('user_id',$user->id)->dbid('id');
			$form1->render();
		}
		else
		{
			$core->err('Can`t find user with ID '.$id);
		}

		$theme->back_button();
	}

	/**
	 * User::delete_user()
	 * Delete user specified by $id
	 * @param mixed $id
	 * @return
	 */
	private function delete_user($id)
	{
		global $core,$theme;

		if($core->get('yesno') == 'true')
		{
			$this->db->query("DELETE FROM ".DB_PREFIX."yaps_user WHERE id = ;",$id);
			$core->refresh_header('admin-pluginsettings?plugin=user');
		}
		else
		{
			$theme->yesno('Do you really want to delete this user?',$core->where_am_i(true,true).'&yesno=true','admin-pluginsettings?plugin=user','Yes','No');
		}
	}

	/**
	 * User::log_as_user()
	 * Log you as user specified by $id
	 * @param mixed $id
	 * @return
	 */
	private function log_as_user($id)
	{
		$this->login_user($id,false);
	}

	/**
	 * User::admin_settings()
	 * Administration settings of plugin, if you can`t administrate anything it`s good to place some example of usage here
	 * It will be printed in administration of Yaps!
	 * @return
	 */
	public function admin_settings()
	{
		global $theme,$core;
		$theme->include_tooltip();

		switch($core->get('action'))
		{
			case 'edit':
				$this->edit_user($core->get('id'));
				return;
			break;
			case 'delete':
				$this->delete_user($core->get('id'));
				return;
			break;
			case 'logas':
				$this->log_as_user($core->get('id'));
				return;
			break;
		}

		echo '<h2>User list</h2>';
		$tab = new Datatable('SELECT U.*, A.`desc` FROM '.DB_PREFIX.'yaps_user U JOIN '.DB_PREFIX.'yaps_user_authlevels A ON U.auth_level = A.auth_level ORDER BY U.login ASC');
		$tab->add_column('Login','login');
		$tab->add_column('Email','email');
		$tab->add_column('Authorization','desc');
		$tab->edit_link('Edit','admin-pluginsettings?plugin=user&action=edit&id={id}','page_white_edit.png');
		$tab->delete_link('Delete','admin-pluginsettings?plugin=user&action=delete&id={id}','cross.png');
		$tab->add_column('Log As',$theme->icon('key.png','Log as this user',true),'admin-pluginsettings?plugin=user&action=logas&id={id}',true);
		$tab->draw_table();

		echo '<br /><h2>User menu</h2>
You can add plugin+action || url and text of link. Here is legend for auth_levels:';
		$tab = new Datatable('SELECT * FROM '.DB_PREFIX.'yaps_user_authlevels ORDER BY auth_level ASC');
		$tab->add_column('Authorization','desc');
		$tab->add_column('Level','auth_level');
		$tab->draw_table();

		echo '<br /><br />';

		$grid = new Datagrid(DB_PREFIX.'yaps_user_menu');
		$grid->add_filter('id');
		$grid->fieldset(false);
		//$grid->style = "width: 100px;";
		$grid->draw_grid();
	}

	/**
	 * User::install()
	 * Install script for this plugin
	 * @return
	 */
	public function install()
	{
		$create_table = $this->db->query("CREATE TABLE `".DB_PREFIX."yaps_user` (
				 `id` int(11) NOT NULL AUTO_INCREMENT,
				 `login` text COLLATE utf8_czech_ci NOT NULL,
				 `email` text COLLATE utf8_czech_ci NOT NULL,
				 `password` varchar(32) COLLATE utf8_czech_ci NOT NULL,
				 `auth_level` int(11) NOT NULL DEFAULT '1',
				 PRIMARY KEY (`id`)
				) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=1");

		$create_table_2 = $this->db->query("CREATE TABLE IF NOT EXISTS `".DB_PREFIX."yaps_user_authlevels` (
				  `desc` text COLLATE utf8_czech_ci NOT NULL,
				  `auth_level` int(11) NOT NULL,
				  PRIMARY KEY (`auth_level`),
				  UNIQUE KEY `auth_level` (`auth_level`)
				) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci");
				

		$create_table_3 = $this->db->query("CREATE TABLE IF NOT EXISTS `".DB_PREFIX."yaps_user_profilefields` (
				  `id` int(11) NOT NULL AUTO_INCREMENT,
				  `name` text COLLATE utf8_czech_ci NOT NULL,
				  `type` enum('NOTHING','TEXT','TEXTAREA','SELECT','RADIO','CHECKBOX','PASSWORD','FILE') COLLATE utf8_czech_ci NOT NULL,
				  PRIMARY KEY (`id`)
				) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=6");

		$create_table_4 = $this->db->query("CREATE TABLE `".DB_PREFIX."yaps_user_userfields` (
				`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
				`id_user` INT NOT NULL ,
				`id_field` INT NOT NULL ,
				`value` TEXT NOT NULL
				) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_czech_ci");

		$create_table_5 = $this->db->query("CREATE TABLE IF NOT EXISTS `".DB_PREFIX."yaps_user_menu` (
			  `id` int(11) NOT NULL AUTO_INCREMENT,
			  `auth_level` text COLLATE utf8_czech_ci NOT NULL,
			  `plugin` varchar(255) COLLATE utf8_czech_ci NOT NULL,
			  `action` varchar(255) COLLATE utf8_czech_ci NOT NULL,
			  `url` text COLLATE utf8_czech_ci NOT NULL,
			  `text` varchar(255) COLLATE utf8_czech_ci NOT NULL,
			  PRIMARY KEY (`id`)
			) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci AUTO_INCREMENT=5");

		$insert_data = $this->db->query("INSERT INTO `".DB_PREFIX."yaps_user_profilefields` (`id`, `name`, `type`) VALUES
				(2, 'Jabber', 'TEXT'),
				(3, 'ICQ', 'TEXT'),
				(4, 'Google Talk', 'TEXT'),
				(5, 'Facebook link', 'TEXT')");

		$insert_data_2 = $this->db->query("INSERT INTO `".DB_PREFIX."yaps_user_authlevels` (`desc`, `auth_level`) VALUES
				('Anonymous', 0),
				('User', 1),
				('Admin', 42)");				

		$insert_data_3 = $this->db->query("INSERT INTO `".DB_PREFIX."yaps_user_menu` (`id`, `auth_level`, `plugin`, `action`, `url`, `text`) VALUES
			(1, '1', 'user', 'login', '', 'Login'),
			(2, '1', 'user', 'register', '', 'Register'),
			(3, '2', 'user', 'profile', '', 'Profile'),
			(4, '2', 'user', 'logout', '', 'Logout')");

		$insert_data_4 = $this->db->query("INSERT INTO ".DB_PREFIX."yaps_config VALUES('plugin_user_installed','true')");

		if($create_table && $create_table_2 && $create_table_3 && $create_table_4 && $create_table_5 && $insert_data && $insert_data_2 && $insert_data_3 && $insert_data_4)
		{
			return true;
		}
		else return false;
	}
}


?>